<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

<title>EU Projects Visualisation</title>

<link rel=stylesheet type=text/css href=http://acl.arts.usyd.edu.au/projects/networkmap/styles.css>
<style>
img.icon { margin-right: 4px; }
</style>

<script src=http://hapi.heuristscholar.org/load?v=02&key=ce1c992c139cfd5a6fdc77c5c71444925f229942></script>
<script src=http://hapi.heuristscholar.org/02/goi.js></script>

<script src="http://maps.google.com/maps?file=api&amp;v=2.105&amp;key=ABQIAAAAWXRbJ6-0zaNuAoz9XBmHZRTOHJksE5z9Wm_cd8XHFESSXyKZQhQ6Wa_KV6YE4tIo4Jn1cD3eEmpr8Q" type="text/javascript"></script>
<xscript src="main-105.js"></xscript>
<script>
var map, cacheMap;
window.console = window.firebug;

GMap2.prototype.cs = function(){this.Ef=true;if(this.ia()){this.nc(null,null,null)}};

GMap2.prototype.zoomAndPan = function(bounds, newZoom) {
	var currentCenter = this.getCenter();
	var newCenter = bounds.getCenter();

	cacheMap.setZoom(newZoom);
	cacheMap.setCenter(newCenter);

	var currentZoom = this.getZoom();

	if (newZoom > currentZoom) {
		// Need to zoom in

		for (var i=currentZoom+1; i <= newZoom; ++i) {
			setTimeout(makeNewTimeoutFunction(newCenter, true, 300 * (i - (currentZoom+1))));
		}

		var handle = GEvent.addListener(map, "zoomend", function(_, endZoom) {
			if (endZoom != newZoom) { return; }
			GEvent.removeListener(handle);
		});
	}
	else if (newZoom < currentZoom) {
		// Need to zoom out

		/* This can get complicated:
		 * Google Maps' smooooooth animation (continuous zoom) goes ugly if the
		 * "focus point" of the zoom out is not actually visible
		 * (i.e. within the bounds of the map)
		 * So, we use a series of midpoints at geometrically increasing intervals.
		 */

		var totalN = (1 << (currentZoom - newZoom)) - 1;
		var n = 0, nIncrement = 1;
		for (var i=currentZoom-1; i >= newZoom; --i) {
			n += nIncrement;
			nIncrement *= 2;
			setTimeout(makeNewTimeoutFunction(calculateMidwayPoint(currentCenter, newCenter, n / totalN), false, 300 * ((currentZoom+1) - i)));
		}
		var handle = GEvent.addListener(map, "zoomend", function(_, endZoom) {
			if (endZoom != newZoom) { return; }
			GEvent.removeListener(handle);
			map.panTo(newCenter);
		});
	}
	else {
		if (! map.fromLatLngToDivPixel(newCenter).equals(map.fromLatLngToDivPixel(currentCenter))) {
			map.panTo(newCenter);
		}
		else {
			/* we don't have to move at all -- we're all done, stop the loading animation */
			moveEndCallback();
		}
	}
};


function GMarkerClusterManager(map) {
	if (map.clusterManager) { return map.clusterManager; }
	this.markers = {};
	this.clusterMarkers = {};

	this.map = map;
	this.collapseIcon = new GIcon(baseIcon);
		this.collapseIcon.image = "http://hapi.heuristscholar.org/samples/collapso-circle.gif";
	this.expandIcon = new GIcon(baseIcon);
		this.expandIcon.image = "http://hapi.heuristscholar.org/samples/expando-circle.gif";
	this.expandedClusters = [];

	map.clusterManager = this;

	GEvent.bind(map, "zoomend", this, this.redrawAllClusters);
}
GMarkerClusterManager.prototype.addMarker = function(marker) {
	var location = marker.getLatLng();
	var index = location.lat() + "," + location.lng();

	marker.originalLatLng = marker.getLatLng();

	if (! this.markers[index]) {
		this.markers[index] = [ marker ];
		this.map.addOverlay(marker);
	}
	else {
		if (this.markers[index].length === 1) {
			// just added a marker to an existing site where there was only one marker before
			this.map.removeOverlay(this.markers[index][0]);
			this.setupClusterMarker(location, index);
		}

		this.markers[index].push(marker);
	}
};
GMarkerClusterManager.prototype.removeMarker = function(marker) {
	var location = marker.originalLatLng;
	var index = location.lat() + "," + location.lng();
	for (var i=0, len=this.markers[index].length; i < len; ++i) {
		if (this.markers[index][i] === marker) {
			this.markers[index].splice(i, 1);
			break;
		}
	}
	this.map.removeOverlay(marker);
	if (marker.connectingLine) {
		this.map.removeOverlay(marker.connectingLine);
	}

	if (this.markers[index].length === 1) {
		// We have just removed the penultimate marker at this point: remove the cluster, restore the original marker
		this.collapseCluster(this.clusterMarkers[index]);

		this.map.removeOverlay(this.clusterMarkers[index]);
		GEvent.removeListener(this.clusterMarkers[index].clickListener);

		this.map.addOverlay(this.markers[index][0]);
	}
};
GMarkerClusterManager.prototype.removeAllMarkers = function() {
	var i, j, len;
	var marker;
	for (j in this.markers) {
		for (i=0, len=this.markers[j].length; i < len; ++i) {
			marker = this.markers[j][i];
			this.map.removeOverlay(marker);
			if (marker.connectingLine) {
				this.map.removeOverlay(marker.connectingLine);
				marker.connectingLine = null;
			}
		}
	}
	this.markers = {};

	for (i in this.clusterMarkers) {
		GEvent.removeListener(this.clusterMarkers[i].clickListener);
		this.map.removeOverlay(this.clusterMarkers[i]);
	}
	this.clusterMarkers = {};

	this.expandedClusters = [];
};

GMarkerClusterManager.prototype.setupClusterMarker = function(location, index) {
	var clusterMarker = new GMarker(location, { icon: this.expandIcon, title: "Click to see all markers at this point" });
	this.clusterMarkers[index] = clusterMarker;
	clusterMarker.index = index;
	clusterMarker.expanded = false;

	var manager = this;
	clusterMarker.clickListener = GEvent.addListener(clusterMarker, "click", function() { manager.handleClusterClick(this); });

	this.map.addOverlay(clusterMarker);
};

GMarkerClusterManager.prototype.handleClusterClick = function(clusterMarker) {
	if (! clusterMarker.expanded) {
		this.expandCluster(clusterMarker);
	}
	else {
		this.collapseCluster(clusterMarker);
	}
};

GMarkerClusterManager.prototype.expandCluster = function(clusterMarker) {
	clusterMarker.expanded = true;

	this.redrawCluster(clusterMarker, true);
	clusterMarker.setImage(this.collapseIcon.image);

	this.expandedClusters.push(clusterMarker);
};

GMarkerClusterManager.prototype.collapseCluster = function(clusterMarker) {
	var markers = this.markers[clusterMarker.index];

	var markerCount = markers.length;
	for (var i=0; i < markerCount; ++i) {
		markers[i].setLatLng(markers[i].originalLatLng);
		this.map.removeOverlay(markers[i].connectingLine);
		markers[i].connectingLine = null;

		this.map.removeOverlay(markers[i]);
		markers[i].connectingLine = null;
	}

	for (i=0; i < this.expandedClusters.length; ++i) {
		if (this.expandedClusters[i] === clusterMarker) {
			this.expandedClusters.splice(i, 1);
			break;
		}
	}

	clusterMarker.setImage(this.expandIcon.image);

	clusterMarker.expanded = false;
};

GMarkerClusterManager.prototype.redrawCluster = function(clusterMarker, isNewCluster) {
	var markers = this.markers[clusterMarker.index];
	var latlng, point;
	var radius = Math.max(30, 8 * markers.length);	// approximation in pixels
	var centerLatLng = clusterMarker.getLatLng();
	var center = this.map.fromLatLngToDivPixel(centerLatLng);

	var hiddenMarker = null;

	var markerCount = markers.length;
	var angle, angleOffset = centerLatLng.lat() * centerLatLng.lng();
	for (var i=0; i < markerCount; ++i) {
		angle = angleOffset + i * Math.PI * 2 / markerCount;
		point = new GPoint( center.x + radius*Math.cos(angle), center.y + radius*Math.sin(angle) );
		latlng = this.map.fromDivPixelToLatLng(point);

		markers[i].setLatLng(latlng);
		this.map.addOverlay(markers[i]);

		if (! isNewCluster) {
			this.map.removeOverlay(markers[i].connectingLine);
		}
		markers[i].connectingLine = new GPolyline([ centerLatLng, latlng ], "#FF0000", 5, 0.7);
		this.map.addOverlay(markers[i].connectingLine);
	}

	if (isNewCluster) {
		/* for a new cluster, move the centre of the map a teeny-tiny bit so we can see it better */
		this.map.panTo(calculateMidwayPoint(map.getCenter(), centerLatLng, 0.1));
	}
};

GMarkerClusterManager.prototype.redrawAllClusters = function() {
	for (var i=0; i < this.expandedClusters.length; ++i) {
		this.redrawCluster(this.expandedClusters[i]);
	}
};



function calculateMidwayPoint(point1, point2, fraction) {
	/* calculate the point some fraction of the way between point1 and point2 */
	return new GLatLng(fraction * point2.lat() + (1-fraction) * point1.lat(), 
	                   fraction * point2.lng() + (1-fraction) * point1.lng());
}

function makeNewTimeoutFunction(center, zoomIn) {
	return function() {
		if (zoomIn) { 
			map.ok(1, true, center, true); 
		}
		else {
			map.ok(-1, true, center, true); 
		}
	}
}



function load() {
	if (! HCurrentUser.isLoggedIn()) {
		alert("You are not logged in to Heurist.\nRedirecting you now ...");
		location.replace("http://heuristscholar.org/heurist/php/login.php?last_uri=" + encodeURIComponent(location.href));
	}
	else if (! HCurrentUser.isInWorkgroup(HWorkgroupManager.getWorkgroupById(19))) {
		alert("You are not in the EUProject workgroup.\nSome records may not be visible to you.");
	}

	if (GBrowserIsCompatible()) {
		// preload images
		cacheMap = new GMap2(document.getElementById("cache-map"));
		cacheMap.setCenter(new GLatLng(52, 10), 4);
		cacheMap.setMapType(G_PHYSICAL_MAP);

		map = new GMap2(document.getElementById("map"));
		map.enableDoubleClickZoom();
		map.enableContinuousZoom();
		map.enableScrollWheelZoom();
		map.addControl(new GSmallMapControl());
		map.setCenter(new GLatLng(52, 10), 4);
		map.setMapType(G_PHYSICAL_MAP);
		GEvent.addListener(map, "moveend", moveEndCallback);

		new GMarkerClusterManager(map);
	}

	loadSearch("ids:"+initialID);
}

function loadSearch(searchString) {
	if (! searchString.match(/\S/)) {
		alert("Enter a search string");
		document.getElementById("q").focus();
		return;
	}

	HeuristScholarDB.loadRecords(new HSearch(searchString), new HLoader(function(search, records) {
		if (! records.length) {
			alert("No matching records");
			return;
		}

		for (var i=0; i < records.length; ++i) { processNewRecord(records[i]); }
		chooseRecord(records[0]);
	}));
}

</script>

</head>
<body class=mainpage onload="load();" style="margin-bottom: 0;">
<script>
var initialID = location.search.replace(/.*id=(\d+).*/, "$1") || 49886;
var chosenRecord = null;
var recordStack = [];	// a list of all the previous records that have been visited
var recordStackIndex = 0;

var relatedDepth = 0;
var knownRecordIDs = [], knownRecordIDsMap = {};
var XField = HDetailManager.getDetailTypeById(210);
var YField = HDetailManager.getDetailTypeById(211);
var geoField = HDetailManager.getDetailTypeById(230);
function processNewRecord(record) {
	var id = record.getID();
	var i;
	var x, y, geo;
	if (! knownRecordIDsMap[id]) {
		knownRecordIDsMap[id] = true;
		knownRecordIDs.push(id);
	}
}

// restrict all searches, loads etc to just the records with a kwd:18004
var BaseSearch = HSearch;
HAPI.Search = HSearch = function(query, options) {
	// don't reload known records
	var excludeIDs = "";
	if (knownRecordIDs) { excludeIDs = "-ids:" + knownRecordIDs.join(",") + " "; }
	BaseSearch.call(this, query+" "+excludeIDs, options);
//        BaseSearch.call(this, "kwd:18004 "+excludeIDs+query, options);
};
HSearch.getClass = function() { return "HSearch"; };
HAPI.inherit(HSearch, BaseSearch);


function chooseRecordCallback() {
	// Callback for GMarker: used with GEvent.bind such that (this) is an HRecord
	chooseRecord(this);
}


function chooseRecord(record, dontAlterStack) {
	var crt = document.getElementById("current-record-title");
	var crl = document.getElementById("current-record-link");
	var cri = document.getElementById("current-record-image");
	var rrList = document.getElementById("other-records");

	crt.innerHTML = "";
	rrList.innerHTML = "Loading ...";
	document.getElementById("loading-div").style.display = "block";

	crt.appendChild(document.createTextNode(record.getTitle()));
	crl.href = "http://heuristscholar.org/heurist-test/edit?bib_id=" + record.getID();
	cri.src = "http://heuristscholar.org/heurist-test/img/reftype/" + (record.getRecordType().getID() || "questionmark") + ".gif";
	cri.style.display = "";
	cri.style.verticalAlign = "baseline";

	chosenRecord = record;
	if (! dontAlterStack) {
		// The record stack keeps track of which records we've previously chosen,
		// but in order to navigate back and forth between records already on the stack we need an override
		// (see gotoPreviousRecord and gotoNextRecord)

		if (recordStackIndex+1 >= recordStack.length) {
			// easy case: we are already looking at the last record on the stack, push the new record on the end
			recordStack.push(chosenRecord);
		}
		else {
			// harder case: there are other records lurking on the stack ABOVE (not including) our current position,
			// and we want to replace those all with one single record (the new record)
			recordStack.splice(recordStackIndex+1, recordStack.length-recordStackIndex-1, chosenRecord);
		}
		recordStackIndex = recordStack.length-1;
	}

	relatedDepth = 0;
	if (! chosenRecord.relatedLoaded) {
		++relatedDepth;
//sm.loadRecords(new HSearch("relatedto:"+_id+" OR linkto:"+_id+" OR linkedto:"+_id), loader);
                //sm.loadRecords(new HSearch("relationsfor:"+_id), loader);

		HeuristScholarDB.loadRecords(new HSearch("kwd:18004 linkedto:"+chosenRecord.getID()+" OR kwd:18004 linkto:"+chosenRecord.getID()+" OR relatedto:"+chosenRecord.getID()),
		                             new HLoader(addAllRelatedLinks));

//		chosenRecord.loadRelated(HeuristScholarDB, new HLoader(addAllRelatedLinks));
		chosenRecord.relatedLoaded = true;
	}
	else {
		addAllRelatedLinks();
	}
}

function addAllRelatedLinks(search, recordSet) {
	clearMap();

	loadPointsAndLines(chosenRecord.getID());

	var i;
	if (search) {
		for (i=0; i < recordSet.length; ++i) { processNewRecord(recordSet[i]); }
	}
	relatedDepth = 0;

	var rrList = document.getElementById("other-records");
	rrList.innerHTML = "&nbsp;";
	document.getElementById("contentframe").style.height = (document.getElementById("contentcell").offsetHeight - 50) + "px";

	rrList.innerHTML = "";

	var relnType;
	var relations, relationsByType, recordTypes, relns;
	var list;
	var rec, recType, relType;

	relations = chosenRecord.getRelationships();
	if (relations.length > 0) {
		relationsByType = {};
		recordTypes = [];

		for (i=0; i < relations.length; ++i) {
			if (relations[i].getPrimaryRecord().getID() === chosenRecord.getID()) {
				rec = relations[i].getSecondaryRecord().getRecord();
				relType = relations[i].getType();
				recType = rec.getRecordType().getID();
			}
			else {
				rec = relations[i].getPrimaryRecord().getRecord();
				relType = relations[i].getInverseType();
				recType = rec.getRecordType().getID();
			}
			if (! rec) { continue; }

			if (relationsByType[recType]) {
				if (relationsByType[recType][relType]) {
					relationsByType[recType][relType].push(rec);
				}
				else {
					relationsByType[recType][relType] = [ rec ];
				}
			}
			else {
				recordTypes.push(recType);
				relationsByType[recType] = {};
				relationsByType[recType][relType] = [ rec ];
			}
		}

		recordTypes.sort(function(a,b){return a-b;});
		for (var j=0; j < recordTypes.length; ++j) {
		    recType = recordTypes[j];

		    rrList.appendChild(document.createElement("hr"));

		    for (relnType in relationsByType[recType]) {
			relns = relationsByType[recType][relnType];
			relns.sort(strcmp);

			var newDiv = document.createElement("div");
			newDiv.className = "relation_type";
			newDiv.appendChild(document.createTextNode(relnType));
			rrList.appendChild(newDiv);

			for (i=0; i < relns.length; ++i) {
				addRelatedRecordLink(rrList, relns[i]);
			}

			rrList.appendChild(document.createElement("br"));
		    }
		}
	}
	else {
		rrList.innerHTML = "<i>No related records</i>";
	}
}
function strcmp(a,b) { var x = a.getTitle(), y = b.getTitle(); return (x < y)? -1 : (x > y)? 1 : 0; }

function addRelatedRecordLink(rrList, record) {
	var newTable = document.createElement("table");
	newTable.className = "resource_table";
	var newTr = newTable.appendChild(document.createElement("tbody")).appendChild(document.createElement("tr"));

	var newTd1 = newTr.appendChild(document.createElement("td"));
	var newTd2 = newTr.appendChild(document.createElement("td"));

	var newA1 = newTd1.appendChild(document.createElement("a"));
	newA1.title = "View resource details";
	newA1.href = "http://heuristscholar.org/heurist-test/legacy/view.php?bib_id=" + record.getID();

	var newImg = newA1.appendChild(document.createElement("img"));
	newImg.src = "http://heuristscholar.org/heurist-test/img/reftype/" + (record.getRecordType().getID() || "questionmark") + ".gif";
	newImg.className = "icon";

	var newA2 = newTd2.appendChild(document.createElement("a"));
	newA2.className = "resource_link";
	newA2.title = "View related resources";
	newA2.href = "#";
	newA2.onclick = function() {
		chooseRecord(record);
		return false;
	};
	newA2.appendChild(document.createTextNode(record.getTitle()));

	rrList.appendChild(newTable);
}


function gotoPreviousRecord() {
	if (recordStackIndex === 0) { return; }	// no previous record

	var previousRecord = recordStack[--recordStackIndex];
	chooseRecord(previousRecord, /* dontAlterStack = */ true);
}
function gotoNextRecord() {
	if (recordStackIndex+1 >= recordStack.length) { return; }	// no "next" record

	var nextRecord = recordStack[++recordStackIndex];
	chooseRecord(nextRecord, /* dontAlterStack = */ true);
}




var markers = [];
var lines = [];
var iconsByRecordType = {};
var baseIcon = new GIcon();
    baseIcon.image = "http://heuristscholar.org/heurist/img/circle.png";
    baseIcon.shadow = "http://heuristscholar.org/heurist/img/circle-shadow.png";
    baseIcon.iconAnchor = new GPoint(13, 13);
    baseIcon.infoWindowAnchor = new GPoint(13, 13);
    baseIcon.iconSize = new GSize(26, 26);
    baseIcon.shadowSize = new GSize(48, 28);
var bounds;


function clearMap() {
	var i;

/*
	for (i=0; i < markers.length; ++i) {
		//map.removeOverlay(markers[i]);
		map.clusterManager.removeMarker(markers[i]);
	}
*/
	map.clusterManager.removeAllMarkers();

	for (i=0; i < lines.length; ++i) {
		map.removeOverlay(lines[i]);
	}
	markers = [];
	lines = [];
}

function plotMap() {
	var i, j, k;
	var recordType;
	var records;
	var marker;

	// clear any existing markers
	clearMap();

	records = chosenRecord.getRelatedRecords();
	for (i=0; i < chosenRecord.locations.length; ++i) {
		// if (chosenRecord.locations[i].depth > 0) { continue; }	// an inherited location
		for (j=0; j < records.length; ++j) {
			if (! records[j].locations) { continue; }
			for (k=0; k < records[j].locations.length; ++k) {
				if (records[j].locations[k].depth > 1) { continue; }	// an inherited location
				if (chosenRecord.locations[i].equals(records[j].locations[k])) { continue; }
				lines.push(new GPolyline([ chosenRecord.locations[i], records[j].locations[k] ], "#0000CC", 3, 0.5));
			}
		}
	}

	var newMarker;
	for (j=0; j < records.length; ++j) {
		recordType = records[j].getRecordType().getID();
		if (! iconsByRecordType[recordType]) {
			iconsByRecordType[recordType] = new GIcon(baseIcon);
			iconsByRecordType[recordType].image = "http://heuristscholar.org/heurist/img/reftype-png/" + recordType + ".png";
		}
		if (! records[j].locations) { continue; }
		for (k=0; k < records[j].locations.length; ++k) {
			if (records[j].locations[k].depth > 1) { continue; }
			newMarker = new GMarker(records[j].locations[k], { icon: iconsByRecordType[recordType], title: records[j].getTitle() });
			GEvent.bind(newMarker, "click", records[j], chooseRecordCallback);
			markers.push(newMarker);
		}
	}

	recordType = chosenRecord.getRecordType().getID();
	if (! iconsByRecordType[recordType]) {
		iconsByRecordType[recordType] = new GIcon(baseIcon);
		iconsByRecordType[recordType].image = "http://heuristscholar.org/heurist/img/reftype-png/" + recordType + ".png";
	}

	for (i=0; i < chosenRecord.locations.length; ++i) {
		newMarker = new GMarker(chosenRecord.locations[i], { icon: iconsByRecordType[recordType], title: chosenRecord.getTitle() });
		markers.push(newMarker);
	}

	for (i=markers.length-1; i >= 0; --i) {
//map.addOverlay(markers[i]);
		map.clusterManager.addMarker(markers[i]);
	}
	for (i=0; i < lines.length; ++i) { map.addOverlay(lines[i]); }

//	map.setZoom(Math.min(map.getBoundsZoomLevel(bounds), 13));
//	map.panTo(bounds.getCenter());
	map.zoomAndPan(bounds, Math.min(map.getBoundsZoomLevel(bounds), 13));
}


function moveEndCallback() {
	document.getElementById("loading-div").style.display = "none";
}


function pointsCallback(vals) {
	var record;
	var i;
	var point;

	bounds = new GLatLngBounds();
	for (var bibID in vals) {
		record = HeuristScholarDB.getRecord(bibID);
		if (! record) { continue; }

		record.locations = [];
		for (i=0; i < vals[bibID].length; ++i) {
			point = new GLatLng(parseFloat(vals[bibID][i][1]), parseFloat(vals[bibID][i][0]));
			point.depth = vals[bibID][i][2];
			record.locations.push(point);
			bounds.extend(point);
		}
	}

	plotMap();
}


function loadPointsAndLines(id) {
	HAPI.XHR.sendRequest("http://hapi.heuristscholar.org/get_points.php?bib_id=" + id, pointsCallback);
}

</script>

<div id=container>
 <div id=banner></div>
 <div id=center>
  <div id=mapcontainer>
   <div id=loading-div style="position: absolute; width: 500px; z-index: 100000;"><img src=../loading-animation.gif style="position: absolute; right: 10px; top: 10px;"></div>
   <div id=map style="width: 500px; height: 640px;"></div>
   <div id=cache-map style="position: absolute; visibility: hidden; top: -1000px; width: 500px; height: 640px;"></div>
<!--
  		<applet codebase="http://acl.arts.usyd.edu.au/map2" 
  			code="org.alov.viewer.SarApplet" 
			name="mapApplet"        
			archive="TMJava.jar"  
			width="500"  height="640" 
			align="right">
   			 <Xparam name="pid" value="20505">
   			 <param name="pid" value="http://acl.arts.usyd.edu.au/projects/networkmap/euprojects/worldmap.tms">
   			 <param name="debug" value="3">
   			 <param name="target" value="contentframe">
   			 <param name="maxsidsize" value="100000">

    			<param name="layout" value="http://acl.arts.usyd.edu.au/projects/networkmap/euprojects/layout.xml">
  		</applet>
-->
  </div>
 </div>
 <div id=right>
  <table border=0 cellpadding=0 cellspacing=0 style="width: 100%; height: 100%;"><tbody>
   
   <tr><td style="height: 20px;">
    <h2>
     <a href=# onclick="gotoPreviousRecord(); return false;" style="float: left; padding: 0 1ex;">back</a>
     <a href=# onclick="gotoNextRecord(); return false;" style="float: left; padding: 0 1ex;">forward</a>
     Resources
    </h2>
   </td></tr>

<!--
   <tr><td style="height: 20px; padding: 0 1em;">
    <form onsubmit="var q = document.getElementById('q').value; loadSearch('relatedto: '+q); return false;" style="float: right;">
     <b>Search: </b>
     <input type="text" style="border: 1px solid gray; width: 30ex;" id="q">
     <input type="submit" value="go" style="font-weight: bold;">
    </form>
   </td></tr>
-->
    <tr><td style="height: 20px;">
    <table class=resource_table><tr>
     <td><h3><a id=current-record-link title="View resource details" href=#
            onclick="window.open(this.href, '', 'status=1,scrollbars=1,width=600,height=500'); return false;"><img id=current-record-image style="display: none;"></a>
         &nbsp;</h3>
     </td>
     <td>
      <h3 id=current-record-title></h3>
     </td>
    </tr></table>
  </td></tr>


  <tr><td style="vertical-align: top;" id="contentcell">
  <div id=contentframe style="overflow: auto;">
   <div class=content>
    <div id=other-records></div>
   </div>
  </div>
  </td></tr>
 </tbody></table>
 </div>
</div>

</body>
</html>
